package com.twu.biblioteca;

import java.io.IOException;
import java.util.*;

/**
 * Created by jfulton on 16/01/2014.
 */
public class LibraryManager {

    private final String MENU_ITEM_MYDETAILS = "0";
    private final String MENU_ITEM_LISTBOOKS = "1";
    private final String MENU_ITEM_LISTMOVIES = "2";
    private final String MENU_ITEM_LOGIN = "3";
    private final String MENU_ITEM_CHECKOUTBOOK = "4";
    private final String MENU_ITEM_CHECKOUTMOVIE = "5";
    private final String MENU_ITEM_RETURNBOOK = "6";
    private final String MENU_ITEM_QUIT = "7";

    private ItemManager<Book> bookManager;
    private ItemManager<Movie> movieManager;
    private Map<String, InputHandler> menuEntryToInputHander;
    private List<UserAccount> userAccounts;
    private UserAccount currentUser;

    private boolean programFinished = false;

    private IOHandler io = new IOHandler();

    public void execute() {
        initBooks();
        initMovies();
        initInputHandlers();
        initUsers();
        showWelcomeMsg();
        listAvailableBooks();
        enterMainLoop();
    }

    public void initBooks() {
        bookManager = new ItemManager<Book>();
        bookManager.addItem(new Book("20,000 Leagues Under the Sea"), 1);
    }

    public void initMovies() {
        movieManager = new ItemManager<Movie>();
        Movie inception = new Movie("Inception", "2010", "Christopher Nolan", 0);
        Movie batman = new Movie("Batman Begins", "2005", "Christopher Nolan", 0);
        movieManager.addItem(inception, 1);
        movieManager.addItem(batman, 1);
    }

    private void enterMainLoop() {
        while (!programFinished) {
            displayMenu();
            try {
                handleMenuInput(io.readLine());
            } catch (IOException e) {
                io.outputLine("Failed to read input!");
                io.outputLine(e.toString());
                programFinished = true;
            }
        }
    }

    public void initUsers() {
        userAccounts = new ArrayList<UserAccount>();
        userAccounts.add(new UserAccount("123-4567", "password", "Bruce Wayne", "bwayne@waynetech.com", "(123) 456"));
        userAccounts.add(new UserAccount("234-5678", "password", "Edward Nigma", "enigma@mensa.org", "(456) 123"));
    }

    public void handleMenuInput(String menuInput) {
        InputHandler handler = menuEntryToInputHander.get(menuInput);
        if (handler == null) {
            handleInvalidOptionChosen();
        } else {
            handler.handleInput();
        }
    }

    public void handleViewMyDetails() {
        if (currentUser != null) {
            io.outputLine("Name: " + currentUser.getName());
            io.outputLine("Email: " + currentUser.getEmail());
            io.outputLine("Phone: " + currentUser.getPhone());
        }
    }

    public void handleInvalidOptionChosen() {
        io.outputLine("Select a valid option!");
    }

    public void showWelcomeMsg() {
        io.outputLine("Welcome to Biblioteca, distinguished user!");
    }

    public void listAvailableBooks() {
        io.outputLine("Books Available:");
        Set<Book> availableBooks = bookManager.getAvailableItems();
        for (Book book : availableBooks) {
            io.outputLine(book.toString());
        }
    }

    public void listAvailableMovies() {
        io.outputLine("Movies Available:");
        for (Movie movie : movieManager.getAvailableItems()) {
            io.outputLine(movie.toString());
        }
    }

    public void displayMenu() {
        io.outputLine("Please select from the following options:");
        if (currentUser != null) {
            io.outputLine(MENU_ITEM_MYDETAILS + " - View my details");
        }
        io.outputLine(MENU_ITEM_LISTBOOKS + " - List Available Books");
        io.outputLine(MENU_ITEM_LISTMOVIES + " - List Available Movies");
        io.outputLine(MENU_ITEM_LOGIN + " - Login");
        io.outputLine(MENU_ITEM_CHECKOUTBOOK + " - Checkout Book");
        io.outputLine(MENU_ITEM_CHECKOUTMOVIE + " - Checkout Movie");
        io.outputLine(MENU_ITEM_RETURNBOOK + " - Return Book");
        io.outputLine(MENU_ITEM_QUIT + " - Exit");
    }

    public void setIoHandler(IOHandler newHandler) {
        io = newHandler;
    }

    private void handleCheckoutBook() {
        String bookTitle = getBookTitleInput();
        try {
            bookManager.checkoutItem(bookTitle);
        } catch (ItemUnavailableException e) {
            io.outputLine("That book is not available.");
        }
        io.outputLine("Thank you! Enjoy the book");

    }

    private void handleCheckoutMovie() {

    }

    public void handleLogin() {
        String libraryNumber, password;
        try {
            io.outputLine("Please enter your library number:");
            libraryNumber = io.readLine();
            io.outputLine("Please enter your password:");
            password = io.readLine();
        } catch (IOException e) {
            io.outputLine("Failed to read library number/password");
            io.outputLine(e.toString());
            return;
        }

        doLogin(libraryNumber, password);
    }

    public void doLogin(String libraryNumber, String password) {
        UserAccount matchingUser = findUserByLibraryNumber(libraryNumber);
        if (matchingUser.getPassword().equals(password)) {
            io.outputLine("Welcome back, " + matchingUser.getName() + ".");
            currentUser = matchingUser;
        } else {
            io.outputLine("Invalid password");
        }
    }

    private UserAccount findUserByLibraryNumber(String libraryNumber) {
        for (UserAccount currentAccount : userAccounts) {
            if (currentAccount.getLibraryNumber().equals(libraryNumber)) {
                return currentAccount;
            }
        }
        return null;
    }

    private void handleQuit() {
        programFinished = true;
    }

    public void returnBookTitled(String title) {
        try {
            bookManager.returnItem(title);
        } catch (CannotReturnItemException e) {
            io.outputLine("That is not a valid book to return.");
        }
        io.outputLine("Thank you for returning the book.");
    }

    private String getBookTitleInput() {
        String title;
        io.outputLine("Please enter a book title:");
        try {
            title = io.readLine();
        } catch (IOException e) {
            title = "";
        }
        return title;
    }

    private void initInputHandlers() {
        menuEntryToInputHander = new HashMap<String, InputHandler>();

        menuEntryToInputHander.put(MENU_ITEM_MYDETAILS, new InputHandler() {
            @Override
            public void handleInput() {
                handleViewMyDetails();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_QUIT, new InputHandler() {
            @Override
            public void handleInput() {
                handleQuit();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_RETURNBOOK, new InputHandler() {
            @Override
            public void handleInput() {
                returnBookTitled(getBookTitleInput());
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_CHECKOUTBOOK, new InputHandler() {
            @Override
            public void handleInput() {
                handleCheckoutBook();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_CHECKOUTMOVIE, new InputHandler() {
            @Override
            public void handleInput() {
                handleCheckoutMovie();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_LOGIN, new InputHandler() {
            @Override
            public void handleInput() {
                handleLogin();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_LISTMOVIES, new InputHandler() {
            @Override
            public void handleInput() {
                listAvailableMovies();
            }
        });

        menuEntryToInputHander.put(MENU_ITEM_LISTBOOKS, new InputHandler() {
            @Override
            public void handleInput() {
                listAvailableBooks();
            }
        });
    }
}
